﻿#include <graphics.h>
#include <math.h>
#include <time.h>
#include <iostream>

#define PI acos(-1)
#define N_Minion 6		//最大小兵数
#define N_Enemy 5		//最大敌方英雄数
#define Width_Map 960		//地图宽度
#define Height_Map 540		//地图高度
#define Width_Minion 640	//小兵区域宽度
#define Height_Minion 360	//小兵区域高度
#define Text_Map 16			//地图字体大小
#define Width_Thresh Width_Map - Width_Minion - Text_Map		//锤石区域宽度
#define Height_Thresh Height_Map - Height_Minion - Text_Map	//锤石区域高度

using namespace std;

MOUSEMSG mouse;

struct Hero
{
	CHAR name[10];
	int x;
	int y;
	int width;
	int coins;
}Thresh;

struct Enemy
{
	CHAR name[10];
	int x;
	int y;
	int width;
	int move;
	int type;
	int gold;
	bool flag;
	DWORD CDstart = 0;
}enemy[N_Enemy + N_Minion];

struct Chain
{
	int x;
	int y;
	int endx;
	int endy;
	double len;
	double angle;
	int v;
	double vx;
	double vy;
	bool flag;
	int max;
	double cd;
	DWORD CDstart = 0;
	int width;
}chain;

void Menu(void);
void Shop(void);
void Init_Hero(void);
void Init_Enemy(void);
void Init_Chain(void);
void Main_Body(void);
void Show_CD(const DWORD&, const DWORD&);
void Show_Statistics(void);
void Move_Hero(void);
void Put_Chain(void);
void Draw_Chain(void);
void Put_Hero(void);
void Move_Enemy(void);
void Move_Yasuo(int i);
void Put_Map(void);
void Put_Enemy(int);
void Boundary_Enemy(int);
void Preview_Chain(void);


int main(void)
{
	initgraph(Width_Map, Height_Map);
	BeginBatchDraw();
	setbkmode(TRANSPARENT);
	Init_Hero();
	Init_Enemy();
	do 
	{
		Menu();
		if (MouseHit())
			mouse = GetMouseMsg();
		if (mouse.x > 400 && mouse.x < 560 && mouse.y > 200 && mouse.y < 240 && mouse.mkLButton == 1)
			Main_Body();
		if (mouse.x > 400 && mouse.x < 560 && mouse.y > 300 && mouse.y < 340 && mouse.mkLButton == 1)
			Shop();
	} while (!(mouse.x > 400 && mouse.x < 560 && mouse.y > 400 && mouse.y < 440 && mouse.mkLButton == 1));
	closegraph();			// 关闭绘图窗口
	return 0;
}

void Menu(void)
{
	mouse.mkLButton = 0;
	settextcolor(WHITE);
	settextstyle(40, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	outtextxy(400, 200, _T("开始游戏"));
	outtextxy(400, 300, _T("进入商店"));
	outtextxy(400, 400, _T("退出游戏"));
	FlushBatchDraw();
}

void Shop(void)
{
	mouse.mkLButton = 0;
	cleardevice();
	do
	{
		cleardevice();
		mouse.mkLButton = 0;
		if (MouseHit())
			mouse = GetMouseMsg();
		settextcolor(WHITE);
		settextstyle(40, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
		outtextxy(0, 0, _T("返回菜单"));
		outtextxy(160, 300, _T("冷却时间"));
		outtextxy(160, 340, _T("减少0.25s"));
		outtextxy(680, 300, _T("勾索长度"));
		outtextxy(680, 340, _T("增加50码"));
		Show_Statistics();
		if(Thresh.coins >= 50 && chain.cd > 0)
			settextcolor(YELLOW);
		else
			settextcolor(DARKGRAY);
		outtextxy(160, 400, _T("升级(50G)"));
		if (Thresh.coins >= 50 && chain.max < 1000)
			settextcolor(YELLOW);
		else
			settextcolor(DARKGRAY);
		outtextxy(680, 400, _T("升级(50G)"));
		settextcolor(WHITE);
		settextstyle(25, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
		for (int i = 0; i < 6; i++)
		{
			outtextxy(165, 150 + 25 * i, _T("图图图图图图"));
			outtextxy(685, 150 + 25 * i, _T("图图图图图图"));
		}
		FlushBatchDraw();
		if (Thresh.coins >= 50)
		{
			if (mouse.x > 160 && mouse.x < 340 && mouse.y > 400 && mouse.y < 440 && mouse.mkLButton == 1 && chain.cd > 0)
			{
				Thresh.coins -= 50;
				chain.cd -= 0.25;
			}
			if (mouse.x > 680 && mouse.x < 860 && mouse.y > 400 && mouse.y < 440 && mouse.mkLButton == 1 && chain.max < 1000)
			{
				Thresh.coins -= 50;
				chain.max += 50;
			}
		}
	} while (!(mouse.x < 160 && mouse.y < 40 && mouse.mkLButton == 1));
	cleardevice();
}

void Init_Hero(void)
{
	Thresh.width = 32;
	Thresh.x = 0;
	Thresh.y = Height_Map - Thresh.width;
	Thresh.coins = 100;
	chain.cd = 4;
	chain.max = 500;
	_stprintf_s(Thresh.name, _T("锤石"));
}

void Init_Enemy(void)
{
	srand(time(NULL));
	for (int i = 0; i < N_Minion; i++)
	{
		enemy[i].width = 32;
		enemy[i].gold = 5;
		_stprintf_s(enemy[i].name, _T("兵"));
	}
	for (int i = N_Minion; i < N_Minion + N_Enemy; i++)
	{
		enemy[i].width = 24;
		enemy[i].gold = 10;
		_stprintf_s(enemy[i].name, _T("索"));
	}
	for (int i = 0; i < N_Minion + N_Enemy; i++)
	{
		enemy[i].flag = true;
		enemy[i].x = rand() % Width_Minion + Width_Thresh + Text_Map;
		enemy[i].y = rand() % Height_Minion;
		enemy[i].move = rand() % 4;
		Boundary_Enemy(i);
		for (int j = 0; j < i; j++)
			while (abs(enemy[j].x - enemy[i].x) < max(enemy[j].width, enemy[i].width) && abs(enemy[j].y - enemy[i].y) < max(enemy[j].width, enemy[i].width))
			{
				enemy[i].x = rand() % Width_Minion + Width_Thresh + Text_Map;
				enemy[i].y = rand() % Height_Minion;
				Boundary_Enemy(i);
			}
	}
}

void Init_Chain(void)
{
	chain.width = 15;
	chain.flag = 0;
	chain.x = Thresh.x + 2 * Thresh.width;
	chain.y = Thresh.y;
	chain.v = 10;
	chain.angle = atan(double(chain.y - mouse.y) / double(mouse.x - chain.x));
	chain.vx = chain.v * cos(chain.angle);
	chain.vy = chain.v * sin(chain.angle);
}

void Main_Body(void)
{
	mouse.mkLButton = 0;
	bool flag;
	DWORD t, start, end;
	start = GetTickCount();
	Init_Enemy();
	srand(time(NULL));
	do
	{
		flag = 1;
		if (MouseHit())
			mouse = GetMouseMsg();
		t = GetTickCount();
		Init_Chain();
		Move_Hero();
		Put_Map();
		Put_Hero();
		Move_Enemy();
		Preview_Chain();
		Show_Statistics();
		settextcolor(WHITE);
		settextstyle(40, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
		outtextxy(0, 0, _T("返回菜单"));
		Show_CD(t, chain.CDstart);
		FlushBatchDraw();
		if (mouse.mkLButton == 1 && t - chain.CDstart > 1000 * chain.cd)
			Put_Chain();
		Sleep(1);
		for (int i = 0; i < N_Enemy + N_Minion; i++)
			if (enemy[i].flag == 1)
				flag = 0;
		if (flag)
		{
			TCHAR s[20];
			Thresh.coins += 100;
			end = GetTickCount();
			_stprintf_s(s, _T("用时%.2fs"), double(end - start) / 1000);
			cleardevice();
			do
			{
				
				if (MouseHit())
					mouse = GetMouseMsg();
				settextstyle(40, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
				settextcolor(WHITE);
				outtextxy(400, 200, s);
				outtextxy(400, 400, _T("返回菜单"));
				settextcolor(YELLOW);
				outtextxy(400, 300, _T("金币+100G"));
				FlushBatchDraw();
			} while (!(mouse.x > 400 && mouse.x < 560 && mouse.y > 400 && mouse.y < 440 && mouse.mkLButton == 1));
			mouse.mkLButton = 0;
			break;
		}
	} while (!(mouse.x < 160 && mouse.y < 40 && mouse.mkLButton == 1));
	cleardevice();
}

void Show_CD(const DWORD& t, const DWORD& coldstart)
{
	TCHAR s[10];
	settextcolor(WHITE);
	settextstyle(32, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	if (t - coldstart < 1000 * chain.cd)
	{
		_stprintf_s(s, _T("%.2fs"), chain.cd - double(t - coldstart)/1000);
		outtextxy(0, 240, s);
	}
	else
		outtextxy(0, 240, _T("ready"));
}

void Show_Statistics(void)
{
	TCHAR s1[20], s2[20], s3[20];
	settextcolor(WHITE);
	settextstyle(30, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	_stprintf_s(s1, _T("冷却时间：%.2fs"), chain.cd);
	outtextxy(0, 60, s1);
	_stprintf_s(s2, _T("勾索长度：%d码"), chain.max);
	outtextxy(0, 120, s2);
	_stprintf_s(s3, _T("金币：%dG"), Thresh.coins);
	outtextxy(0, 180, s3);
}

void Move_Hero()
{
	if (GetAsyncKeyState(87) & 0x8000)
		Thresh.y -= 1;
	if (GetAsyncKeyState(83) & 0x8000)
		Thresh.y += 1;
	if (GetAsyncKeyState(65) & 0x8000)
		Thresh.x -= 1;
	if (GetAsyncKeyState(68) & 0x8000)
		Thresh.x += 1;
	if (Thresh.x < 0)
		Thresh.x = 0;
	if (Thresh.x > Width_Thresh - 2 * Thresh.width)
		Thresh.x = Width_Thresh - 2 * Thresh.width;
	if (Thresh.y > Height_Map - Thresh.width)
		Thresh.y = Height_Map - Thresh.width;
	if (Thresh.y < Height_Minion + Text_Map)
		Thresh.y = Height_Minion + Text_Map;
}

void Put_Chain(void)
{
	int j = 0;
	chain.CDstart = GetTickCount();
	for (chain.endx = chain.x, chain.endy = chain.y, chain.len = 0; chain.len < chain.max; chain.endx += chain.vx, chain.endy -= chain.vy)
	{
		Put_Map();
		Put_Hero();
		chain.len = sqrt((chain.endx - chain.x) * (chain.endx - chain.x) + (chain.y - chain.endy) * (chain.y - chain.endy));
		Draw_Chain();
		for (j = 0; j < N_Enemy + N_Minion; j++)
			if (abs(chain.endx - enemy[j].x) <= enemy[j].width && abs(chain.endy - enemy[j].y) <= enemy[j].width && enemy[j].flag == 1)
			{
				chain.flag = 1;
				enemy[j].flag = 0;
				Thresh.coins += enemy[j].gold;
				break;
			}
		if (chain.flag == 1)
		{
			for (enemy[j].flag = 1; chain.endx > chain.x; chain.endx -= chain.vx, chain.endy += chain.vy)
			{
				Put_Map();
				Put_Hero();
				Draw_Chain();
				enemy[j].x = chain.endx;
				enemy[j].y = chain.endy;
				for (int i = 0; i < N_Enemy + N_Minion; i++)
					Put_Enemy(i);
				FlushBatchDraw();
				Sleep(10);
			}
			enemy[j].flag = 0;
			break;
		}
		Move_Enemy();
		FlushBatchDraw();
		Sleep(10);
	}
}

void Draw_Chain()
{
	int x = chain.x;
	int y = chain.y;
	settextcolor(WHITE);
	settextstyle(chain.width, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	for (; x < chain.endx; x += chain.vx, y -= chain.vy)
		outtextxy(x, y, _T("勾"));
}

void Put_Hero(void)
{
	settextcolor(WHITE);
	settextstyle(Thresh.width, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	outtextxy(Thresh.x, Thresh.y, Thresh.name);
}

void Move_Enemy(void)
{
	DWORD t = GetTickCount();
	if (t % 2000 < 500)
		for (int i = 0; i < N_Enemy + N_Minion; i++)
		{
			Move_Yasuo(i);
			switch (enemy[i].move)
			{
			case 0:
				enemy[i].x -= 1;
				enemy[i].y -= 1;
				break;
			case 1:
				enemy[i].x -= 1;
				enemy[i].y += 1;
				break;
			case 2:
				enemy[i].x += 1;
				enemy[i].y -= 1;
				break;
			case 3:
				enemy[i].x += 1;
				enemy[i].y += 1;
				break;
			}
			Boundary_Enemy(i);
			Put_Enemy(i);
		}
	if (t % 2000 > 499 && t % 2000 < 1000)
		for (int i = 0; i < N_Enemy + N_Minion; i++)
		{
			Move_Yasuo(i);
			switch (enemy[i].move)
			{
			case 0:
				enemy[i].x -= 1;
				enemy[i].y += 1;
				break;
			case 1:
				enemy[i].x += 1;
				enemy[i].y += 1;
				break;
			case 2:
				enemy[i].x -= 1;
				enemy[i].y -= 1;
				break;
			case 3:
				enemy[i].x += 1;
				enemy[i].y -= 1;
				break;
			}
			Boundary_Enemy(i);
			Put_Enemy(i);
		}
	if (t % 2000 > 999 && t % 2000 < 1500)
		for (int i = 0; i < N_Enemy + N_Minion; i++)
		{
			Move_Yasuo(i);
			switch (enemy[i].move)
			{
			case 0:
				enemy[i].x += 1;
				enemy[i].y += 1;
				break;
			case 1:
				enemy[i].x += 1;
				enemy[i].y -= 1;
				break;
			case 2:
				enemy[i].x -= 1;
				enemy[i].y += 1;
				break;
			case 3:
				enemy[i].x -= 1;
				enemy[i].y -= 1;
				break;
			}
			Boundary_Enemy(i);
			Put_Enemy(i);
		}
	if (t % 2000 > 1499)
		for (int i = 0; i < N_Enemy + N_Minion; i++)
		{
			switch (enemy[i].move)
			{
			case 0:
				enemy[i].x += 1;
				enemy[i].y -= 1;
				break;
			case 1:
				enemy[i].x -= 1;
				enemy[i].y -= 1;
				break;
			case 2:
				enemy[i].x += 1;
				enemy[i].y += 1;
				break;
			case 3:
				enemy[i].x -= 1;
				enemy[i].y += 1;
				break;
			}
			Boundary_Enemy(i);
			Put_Enemy(i);
		}
	if(t % 4000 > 3949)
		for (int i = 0; i < N_Minion + N_Enemy; i++)
			enemy[i].move = rand() % 4;
}

void Move_Yasuo(int i)
{
	DWORD t = GetTickCount();
	if (i >= N_Minion && t - enemy[i].CDstart > 2500)
		for (int j = 0; j < N_Enemy; j++)
			if (abs(enemy[i].x - enemy[j].x) <= enemy[i].width && abs(enemy[i].y - enemy[j].y) <= enemy[i].width && enemy[j].flag == 1)
			{
				enemy[i].x = 2 * enemy[j].x - enemy[i].x;
				enemy[i].CDstart = GetTickCount();
				break;
			}
}

void Put_Map(void)
{
	cleardevice();
	settextcolor(WHITE);
	settextstyle(Text_Map, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	for (int i = 0; Text_Map * i < Width_Thresh; i++)
		outtextxy(Text_Map * i, Height_Minion, _T("墙"));
	for (int i = 0; Text_Map * i < Height_Thresh; i++)
		outtextxy(Width_Thresh, Height_Minion + Text_Map * i, _T("墙"));
	settextstyle(32, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	for (int i = 1; i < 4; i++)
	{
		outtextxy(Width_Thresh + 160 * i, Height_Map - 32, _T("木"));
		outtextxy(Width_Thresh + 160 * i - 32, Height_Map - 64, _T("树树树"));
		outtextxy(Width_Thresh + 160 * i, Height_Map - 96, _T("树"));
	}
}

void Put_Enemy(int i)
{
	settextcolor(WHITE);
	if (enemy[i].flag == true)
	{
		settextstyle(enemy[i].width, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
		outtextxy(enemy[i].x, enemy[i].y, enemy[i].name);
	}
}

void Boundary_Enemy(int i)
{
	if (enemy[i].x < Width_Thresh + Text_Map)
		enemy[i].x = Width_Thresh + Text_Map;
	if (enemy[i].x > Width_Map - enemy[i].width)
		enemy[i].x = Width_Map - enemy[i].width;
	if (enemy[i].y < 0)
		enemy[i].y = 0;
	if (enemy[i].y > Height_Minion - enemy[i].width)
		enemy[i].y = Height_Minion - enemy[i].width;
}

void Preview_Chain(void)
{
	settextcolor(LIGHTGRAY);
	settextstyle(chain.width, 0, _T("Consolas"), 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	if(mouse.x > Width_Thresh && mouse.y < Height_Minion)
		for (chain.endx = chain.x, chain.endy = chain.y, chain.len = 0; chain.len < chain.max; chain.endx += chain.vx, chain.endy -= chain.vy)
		{
			outtextxy(chain.endx, chain.endy, _T("勾"));
			chain.len = sqrt((chain.endx - chain.x) * (chain.endx - chain.x) + (chain.y - chain.endy) * (chain.y - chain.endy));
		}
}
